
#include <stdio.h>
#include <limits.h>

#include "mm.h"

/*

Derek Anderson
Connar Grimley

These are tests we created to test our code. Have fun.


Test zero	- the given test in the assignment writeup
Test one 	- tests that you access the whole memory pool,
			  and allocating two pointers next to eachother
			  sets them at the correct distance apart.
Test two 	- tests that if you create two pointers, then
			  remove the first, you can then write into the
			  space that was freed
Test three 	- tests that you can assign things to pointers
Test four 	- tests the output of the 4 functions when there
			  was no mm created
Test five 	- tests to see the data assigned to a pointer was
			  put in the correct place
Test six 	- tests that it will output an error when you run
			  out of room to put pointers in
Test seven 	- tests initializing two mm's
Test eight 	- tests asking for a too large of mm
Test nine 	- tests allocating 0 bytes
Test ten 	- tests allocating more bytes than available
Test eleven - calls mm_init(0), which should cause an error?

Extra Credit Tests:
	EC Test zero  - the given EC test in the assignment writeup
	EC Test one   - tests that barriers keep the correct scope
	EC Test two   - tests consecutive barriers work correctly
	EC Test three - tests a barrier_end without a barrier_start
	EC Test four  - tests the output of barrier (end & start) when
	                there is no mm existing
	EC Test five  - tests the results of calling barrier_start without
	                calling barrier_end afterwards

To run a test: Uncomment the corresponding line below.
*/
//#define TEST_ZERO
//#define TEST_ONE
//#define TEST_TWO
//#define TEST_THREE
//#define TEST_FOUR
//#define TEST_FIVE
//#define TEST_SIX
//#define TEST_SEVEN
//#define TEST_EIGHT
#define TEST_NINE
#define TEST_TEN
//#define TEST_EC_ZERO
//#define TEST_EC_ONE
//#define TEST_EC_TWO
//#define TEST_EC_THREE
//#define TEST_EC_FOUR
//#define TEST_EC_FIVE

//------------------Test Code below!---------------------//

int main()
{
    char *ptr1, *ptr2, *ptr3, *ptr4, *ptr5;
    int i;
	int b0, b1, b2, b3;

#ifdef TEST_ZERO
//test.c
	printf("\n~~given test.c~~\n");
	printf("should print out buffer overflow error\n");
	printf("should print out two free errors\n");
	printf("should print out 1 memory leak, 1 buffer overflow, 2 free errors\n");
	printf("~~~~\n");
        // initialize the memory library
        mm_init(4000); // memory pool size = 4000 bytes

        // Allocate 10 bytes
        ptr1=mm_alloc(10);

        for (i=0; i<11;i++) {
                // Should return buffer overflow error on 11th iteration
                mm_assign(ptr1+i,(char)i); // It is similar to ptr1[i] = (char)i
        }
        ptr2=ptr1+5;

        // Should return error since ptr2 is not the original ptr
        // returned by earlier mm_alloc.
        mm_free(ptr2);
        mm_free(ptr2); // free error again

        //ptr1 was allocated but not freed.
        mm_end();
#endif

#ifdef TEST_ONE
// TEST ONE
	printf("\n~~TEST ONE~~\n");
	printf("~~should run with no errors\n");
    mm_init(4000); // memory pool size = 4000 bytes

    ptr1=mm_alloc(10);
	ptr2=mm_alloc(3990);

	mm_free(ptr2);
	mm_free(ptr1);

    mm_end();
#endif

#ifdef TEST_TWO
// TEST TWO
	printf("\n~~TEST TWO~~\n");
	printf("~~should run with no errors\n");
    mm_init(4000); // memory pool size = 4000 bytes

    ptr1=mm_alloc(10);
	ptr2=mm_alloc(3990);

	mm_free(ptr1);

	ptr3=mm_alloc(5);

	mm_free(ptr2);
	mm_free(ptr3);

    mm_end();
#endif

#ifdef TEST_THREE
// TEST THREE
	printf("\n~~TEST THREE~~\n");
	printf("~~should run with no errors\n");
    mm_init(4000); // memory pool size = 4000 bytes

    ptr1=mm_alloc(10);
	ptr2=mm_alloc(20);
	ptr3=mm_alloc(5);

	mm_assign(ptr1, (char)1);
	mm_assign(ptr2, (char)1);
	mm_assign(ptr3, (char)1);

	mm_free(ptr1);
	mm_free(ptr2);
	mm_free(ptr3);

    mm_end();
#endif

#ifdef TEST_FOUR
// TEST FOUR
	printf("\n~~TEST FOUR~~\n");
	printf("~~should print 4 different errors, about not being in an mm\n");
	mm_alloc(50);
	mm_free((char*)743);
	mm_assign((char*)682, 'c');
    mm_end();
#endif

#ifdef TEST_FIVE
// TEST FIVE
	printf("\n~~TEST FIVE~~\n");
	printf("~~should print 1234567890\n");
    mm_init(10); // memory pool size = 4000 bytes

    ptr1=mm_alloc(10);

	mm_assign(ptr1, '1');
	mm_assign(ptr1+1, '2');
	mm_assign(ptr1+2, '3');
	mm_assign(ptr1+3, '4');
	mm_assign(ptr1+4, '5');
	mm_assign(ptr1+5, '6');
	mm_assign(ptr1+6, '7');
	mm_assign(ptr1+7, '8');
	mm_assign(ptr1+8, '9');
	mm_assign(ptr1+9, '0');

	for(i=0; i<10; i++){
		printf("%c",ptr1[i]);
	}
	printf("\n~~should run with no errors\n");

	mm_free(ptr1);
    mm_end();
#endif

#ifdef TEST_SIX
// TEST SIX
	printf("\n~~TEST SIX~~\n");
	printf("~~should print 2 errors, not enough room to allocate, and not a pointer to free\n");

 	char *ptrs[6];
	mm_init(80);

	for (i=0; i<6;i++) {
		ptrs[i] = mm_alloc(16);
	}
	for (i=0; i<6;i++) {
		mm_free(ptrs[i]);
	}

	printf("~~should run with 1 free error\n");
	mm_end();
#endif

#ifdef TEST_SEVEN
// TEST SEVEN
	printf("\n~~TEST SEVEN~~\n");

	mm_init(10);
	printf("~~should print out that mm was already initialized\n");
	mm_init(10);

	printf("~~should run with no errors\n");
	mm_end();
	printf("~~should print out that mm was never initialized\n");
	mm_end();
#endif

#ifdef TEST_EIGHT
// TEST EIGHT
	printf("\n~~TEST EIGHT~~\n");
	printf("~~should print out that mm could not be initialized\n");
	i = mm_init(ULONG_MAX);

	printf("~~should print out -1\n");
	printf("%d\n",i);

	printf("~~should print out that mm was never initialized\n");
	mm_end();
#endif

#ifdef TEST_NINE
// TEST NINE
	printf("\n~~TEST NINE~~\n");
	mm_init(10);

	printf("~~should print a warning, allocating 0 chars\n");
	ptr1 = mm_alloc(0);

	printf("~~should be NULL\n%p\n",ptr1);

	printf("~~should run with no errors\n");
	mm_end();
#endif

#ifdef TEST_TEN
// TEST TEN
	printf("\n~~TEST TEN~~\n");
	mm_init(10);

	printf("~~should print an error message, not enough space\n");
	ptr1 = mm_alloc(20);

	printf("~~should run with no errors\n");
	mm_end();
#endif

#ifdef TEST_ELEVEN
// TEST TEN
	printf("\n~~TEST ELEVEN~~\n");
	printf("~~should print a warning that init was passed 0 for size\n");
	mm_init(0);
	mm_end();
#endif

#ifdef TEST_EC_ZERO
//their extra credit tests
	printf("\n~~GIVEN EXTRA CREDIT TEST~~\n");
	printf("should print out 2 buffer overflow errors\n");
	printf("should print out 1 free error\n");
	printf("should print out 2 memory leak, 2 buffer overflow, 1 free errors\n");
	printf("should print out : b0=1, b1=0\n");
	printf("~~~~\n");

     // initialize the memory library
     mm_init(4000); // memory pool size = 4000 bytes

     ptr1=mm_alloc(10);
     //Start barrier 0
     mm_barrier_start(); //The first start
     for (i=0; i<11;i++) {
        // Should return buffer overflow error on 11th iteration
        mm_assign(ptr1+i,(char)i);
        // It is similar to ptr1[i] = (char)i
    }

     //Start barrier 1
     mm_barrier_start();//The second start
     ptr2=mm_alloc(1);
     mm_assign(ptr2+1, (char)2); //Buffer overflow error
     mm_free(ptr2);

     //End barrier 1
     b1 = mm_barrier_end();//The first end should match the second start
     mm_free (ptr2); // Double free
     ptr3=mm_alloc(1);
     mm_assign(ptr3, (char)3);

     // End barrier 0
     b0 = mm_barrier_end();//The second end should match the first start

     mm_end();

     printf("b0=%d, b1=%d\n",b0,b1);
#endif

#ifdef TEST_EC_ONE
// TEST Extra Credit One
	printf("\n~~EXTRA CREDIT TEST ONE~~\n");
	mm_init(10); // memory pool size = 10 bytes

	mm_barrier_start();
	ptr1 = mm_alloc(5);

	mm_barrier_start();
	ptr2 = mm_alloc(5);

	b1 = mm_barrier_end();
	b0 = mm_barrier_end();


	mm_free(ptr1);
	mm_free(ptr2);

	printf("~~should print this: b0=2, b1=1\n");
	printf("b0=%d, b1=%d\n",b0,b1);
	printf("~~should run with no errors\n");
	mm_end();
#endif

#ifdef TEST_EC_TWO
// TEST Extra Credit Two
	printf("\n~~EXTRA CREDIT TEST TWO~~\n");
	mm_init(25); // memory pool size = 25 bytes

	mm_barrier_start();
	ptr1 = mm_alloc(5);

	mm_barrier_start();
	ptr2 = mm_alloc(5);
	ptr3 = mm_alloc(5);
	b1 = mm_barrier_end();
	b0 = mm_barrier_end();

	mm_barrier_start();
	ptr4 = mm_alloc(1);
	b2 = mm_barrier_end();

	mm_barrier_start();
	ptr5 = mm_alloc(5);
	mm_free(ptr3);
	mm_free(ptr5);
	mm_barrier_end();

	mm_free(ptr1);
	mm_free(ptr2);

	printf("~~should print this: b0=3, b1=2, b2=1, b3=0\n");
	printf("b0=%d, b1=%d, b2=%d, b3=%d\n",b0,b1,b2,b3);
	printf("~~should run with one memory leak\n");
	mm_end();
#endif

#ifdef TEST_EC_THREE
// TEST Extra Credit Three
	printf("\n~~EXTRA CREDIT TEST THREE~~\n");
	mm_init(25); // memory pool size = 25 bytes
	printf("~~should print an error about not having a matching barrier start\n");
	mm_barrier_end();
	printf("~~should run with no errors\n");
	mm_end();
#endif

#ifdef TEST_EC_FOUR
// TEST Extra Credit Four
	printf("\n~~EXTRA CREDIT TEST FOUR~~\n");
	printf("~~should print 3 errors about not being in an mm\n");
	mm_barrier_start();
	mm_barrier_end();
	mm_end();
#endif

#ifdef TEST_EC_FIVE
// TEST Extra Credit Five 
//  We are not sure if this should cause an error or not
	printf("\n~~EXTRA CREDIT TEST FIVE~~\n");
	printf("This is may or may not do something\n");
	printf("We are unsure if this is supposed to cause an error or not\n");
	mm_init(100);
	mm_barrier_start();
	mm_end();
#endif
	
#if !defined(TEST_ONE) && !defined(TEST_TWO) && !defined(TEST_THREE) && !defined(TEST_FOUR) && !defined(TEST_FIVE) && !defined(TEST_SIX) && !defined(TEST_SEVEN) && !defined(TEST_EIGHT) && !defined(TEST_NINE) && !defined(TEST_TEN) && !defined(TEST_ELEVEN) && !defined(TEST_ZERO) && !defined(TEST_EC_ZERO) && !defined(TEST_EC_ONE) && !defined(TEST_EC_TWO) && !defined(TEST_EC_THREE) && !defined(TEST_EC_FOUR) && !defined(TEST_EC_FIVE)

	printf("\nEvery test is commented out\n");
	printf("Go into test.c and uncomment one or more of the lines (47 to 64) to run those tests \n\n");
#endif

//using all the variables, so that if one is used, yet the test is commented out, it wont shout out a warning
    ptr1 = ptr2 = ptr3 = ptr4 = ptr5 = NULL;
	i = b0 = b1 = b2 = b3 = 5;
	printf("\n");
	return 0;
}
